#include "CEmitter.h"
#include "CParticle.h"
#include "Wrappers\CSGD_TextureManager.h"
#include "Wrappers\CSGD_Direct3D.h"
#include <math.h>
#include <d3dx9.h>
#include <D3d9types.h>
#include "Game Objects\CBase.h"
#include "Game Objects\CCamera.h"

CEmitter::CEmitter(int nNumParticles, int nEmitterHeight, int nEmitterWidth, 
		float fParticleLife, float fStartParticleScale, int PosX, int PosY, int ImageID, float VelX, float Vely, int angle, float BeginA, 
		float BeginR, float BeginG, float BeginB, float DA, float DR, float DG, float DB, float DS, bool Looping, int source, int dest, float aX, float aY)
{
	Count = nNumParticles; 
	Height = nEmitterHeight;
	Width = nEmitterWidth;
	Life = fParticleLife;
	Beginscale = fStartParticleScale;
	this->PosX = 200;//PosX;
	this->PosY = 200;//PosY;
	this->ImageID = ImageID;
	this->VelX = VelX;
	this->VelY = Vely;
	permavelX = VelX;
	permavelY = VelY;
	this->angle = angle;
	this->BeginA = BeginA;
	this->BeginR = BeginR;
	this->BeginG = BeginG;
	this->BeginB = BeginB;
	this->DA = DA;
	this->DR = DR;
	this->DG = DG;
	this->DB = DB;
	this->DS = DS;
	this->Looping = Looping;
	this->YAcel = aY;
	this->XAcel = aX;
	this->sourceblend = source;
	this->destblend = dest;
	
	for(int i = 0; i < Count; i++)
	{
		CParticle* temp = new CParticle;
		deadparticles.push_back(temp);

		ResetParticle(i);
	}
	totalspawntime = 0.0f;
	object = NULL;
	isplaying = false;
	
}
CEmitter::~CEmitter(void)
{
	for(unsigned int i = 0; i < liveparticles.size(); i++)
	{
		delete liveparticles[i];//free(liveparticles[i]);
	}
	
	for(unsigned int i = 0; i < deadparticles.size(); i++)
	{
		delete deadparticles[i];//free(deadparticles[i]);
	}
}
void CEmitter::ResetParticle(int index)
{	
	if(Width != 0)
	{
		deadparticles[index]->PosX = (float)(rand() % Width - (Width / 2));
		deadparticles[index]->PosX += this->PosX;
	}
	else
		deadparticles[index]->PosX = (float)this->PosX;

	if(Height != 0)
	{
		deadparticles[index]->PosY = (float)(rand() % Height - (Height / 2));
		deadparticles[index]->PosY += this->PosY;
	}
	else
		deadparticles[index]->PosY = (float)this->PosY;
    					
    deadparticles[index]->LiveTime = Life;
	float tempangle = 0;
	if(angle)
		tempangle = (float)(rand() % angle - (angle / 2));
    D3DXVECTOR2 tempvec(VelX, VelY);
    D3DXVECTOR2 tempvec2;
	
	D3DXVec2Normalize(&tempvec, &tempvec);
    
	tempvec2.x = (float)((VelX * (cos(DegreeToRadian(tempangle)))) - (sin(DegreeToRadian(tempangle)) * VelY));
    tempvec2.y = (float)((VelY * (cos(DegreeToRadian(tempangle)))) + (sin(DegreeToRadian(tempangle)) * VelX));
    tempvec2.y = -tempvec2.y;
                

    deadparticles[index]->VelX = tempvec2.x;
    deadparticles[index]->VelY = tempvec2.y;

    deadparticles[index]->A = BeginA;
    deadparticles[index]->R = BeginR;
    deadparticles[index]->G = BeginG;
    deadparticles[index]->B = BeginB;



    deadparticles[index]->scale = Beginscale;
}
float CEmitter::DegreeToRadian(float angle)
{
	return D3DX_PI * angle / 180.0f;
}
void CEmitter::update(float elapsedtime)
{

	if(object)
	{
		PosX = (int)object->GetPosX() + objX;
		PosY = (int)object->GetPosY() + objY;
		if(object->GetVelX() != 0)
			VelX = -object->GetVelX() / 2;
		if(object->GetVelY() != 0)
			VelY = object->GetVelY() / 2;
		
	}

	totalspawntime += elapsedtime;
	if (totalspawntime >= .01 && deadparticles.size() > 0)
    {
        if (Looping)
        {
            ResetParticle(0);
			liveparticles.push_back(deadparticles[0]);
			deadparticles.erase(deadparticles.begin());
            totalspawntime = 0.0f;
        }
        else
        {
            for (int i = 0; i < Count; i++)
            {
                if (deadparticles.size() > 0)
                {
                    ResetParticle(0);
                    liveparticles.push_back(deadparticles[0]);
					deadparticles.erase(deadparticles.begin());
                }
            }
            totalspawntime = 0.0f;
        }

    }
    if (liveparticles.size() > 0)
    {
        for (unsigned int i = 0; i < liveparticles.size(); i++)
        {
            liveparticles[i]->VelY += YAcel * (float)elapsedtime;
            liveparticles[i]->VelX += XAcel * (float)elapsedtime;
            liveparticles[i]->PosY += liveparticles[i]->VelY * (float)elapsedtime;
            liveparticles[i]->PosX += liveparticles[i]->VelX * (float)elapsedtime;

            liveparticles[i]->A += DA * (float)elapsedtime;
            liveparticles[i]->R += DR * (float)elapsedtime;
            liveparticles[i]->G += DG * (float)elapsedtime;
            liveparticles[i]->B += DB * (float)elapsedtime;
            if (liveparticles[i]->A > 255)
                liveparticles[i]->A = 255;
            else if (liveparticles[i]->A < 0)
                liveparticles[i]->A = 0;
            if (liveparticles[i]->R > 255)
                liveparticles[i]->R = 255;
            else if (liveparticles[i]->R < 0)
                liveparticles[i]->R = 0;
            if (liveparticles[i]->G > 255)
                liveparticles[i]->G = 255;
            else if (liveparticles[i]->G < 0)
                liveparticles[i]->G = 0;
            if (liveparticles[i]->B > 255)
                liveparticles[i]->B = 255;
            else if (liveparticles[i]->B < 0)
                liveparticles[i]->B = 0;

            liveparticles[i]->scale += DS * (float)elapsedtime;
            liveparticles[i]->LiveTime -= elapsedtime;
            if (Looping)
            {
                if (liveparticles[i]->LiveTime <= 0.0f)
                {
                    deadparticles.push_back(liveparticles[i]);
					liveparticles.erase(liveparticles.begin() + i);

                }
            }
            else if(liveparticles[i]->LiveTime <= 0.0f)
            {
              liveparticles.erase(liveparticles.begin() + i);
            }
        }
    }
}
void CEmitter::render()
{
	if (liveparticles.size() > 0 && (int)liveparticles.size() <= Count)
	{

		for(unsigned int i = 0; i < liveparticles.size(); i++)
		{
			CSGD_Direct3D::GetInstance()->GetSprite()->Flush();
			CSGD_Direct3D::GetInstance()->GetDirect3DDevice()->SetRenderState(D3DRS_SRCBLEND, sourceblend);
			CSGD_Direct3D::GetInstance()->GetDirect3DDevice()->SetRenderState(D3DRS_DESTBLEND, destblend);
			CSGD_TextureManager::GetInstance()->Draw(ImageID, (int)liveparticles[i]->PosX - CCamera::GetInstance()->GetOffsetX() + 15, (int)liveparticles[i]->PosY - CCamera::GetInstance()->GetOffsetY() + 15, 
				liveparticles[i]->scale, liveparticles[i]->scale, (RECT*)0, 0, 0, 0,D3DCOLOR_ARGB((int)liveparticles[i]->A, (int)liveparticles[i]->R, (int)liveparticles[i]->G, (int)liveparticles[i]->B));
			CSGD_Direct3D::GetInstance()->GetSprite()->Flush();

			CSGD_Direct3D::GetInstance()->GetDirect3DDevice()->SetRenderState(D3DRS_SRCBLEND, (DWORD)5);
			CSGD_Direct3D::GetInstance()->GetDirect3DDevice()->SetRenderState(D3DRS_DESTBLEND, (DWORD)6);

		}
	}
}
void CEmitter::SetObject(CBase* object, int offsetx, int offsety)
{
	this->object = object;
	objX = offsetx;
	objY = offsety;
}
CEmitter::CEmitter(CEmitter& copied)
{

	Life = copied.Life;
	Count = copied.Count;
	Width = copied.Width;
	Height = copied.Height;
	PosX = copied.PosX;
	PosY = copied.PosY;
	ImageID = copied.ImageID;
	VelX = copied.VelX;
	VelY = copied.VelY;
	angle = copied.angle;
	BeginA = copied.BeginA;
	BeginR = copied.BeginR;
	BeginG = copied.BeginG;
	BeginB = copied.BeginB;
	DA = copied.DA;
	DR = copied.DR;
	DG = copied.DG;
	DB = copied.DB;
	Beginscale = copied.Beginscale;
	DS = copied.DS;
	Looping = copied.Looping;
	totalspawntime = copied.totalspawntime;
	YAcel = copied.YAcel;
	XAcel = copied.XAcel;
	sourceblend = copied.sourceblend;
	destblend = copied.destblend;
	object = copied.object;
	objX = copied.objX;
	objY = copied.objY;
	isplaying = copied.isplaying;
	permavelX = copied.permavelX;
	permavelY = copied.permavelY;


	for(unsigned int i = 0; i < copied.deadparticles.size(); i++)
	{
		deadparticles.push_back(new CParticle(*copied.deadparticles[i]));
	}
	for(unsigned int i = 0; i < copied.liveparticles.size(); i++)
	{
		liveparticles.push_back(new CParticle(*copied.liveparticles[i]));
	}

}